﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using viBook.Common;
using viBook.Helpers;
using viBook.Models;

namespace viBook.Repositories
{
    public class BookCommentRepository : IBookCommentRepository
    {
        private readonly viBookContext _context = new viBookContext();

        #region IBookCommentRepository Members

        public IQueryable<BookComment> All
        {
            get { return _context.BookComments; }
        }

        public BookComment Find(int id)
        {
            var bookcomments = _context.BookComments.Find(id);
            if (bookcomments != null)
            {
                bookcomments.User = _context.Users.Find(bookcomments.UserId);
            }
            return bookcomments;
        }

        public void InsertOrUpdate(BookComment bookComment)
        {
            if (bookComment.Id == 0)
            {
                bookComment.CreatedDate = DateTime.Now;
                _context.BookComments.Add(bookComment);
                Save();
                Book book = _context.Books.Find(bookComment.BookId);
                book.NumberOfComments++;
                Save();
            }
        }

        public void Delete(int id)
        {
            BookComment bookComment = _context.BookComments.Find(id);
            _context.BookComments.Remove(bookComment);
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public DataFeedback Like(int id, int userId)
        {
            var feedback = new DataFeedback();
            var existLike = _context.BookCommentLikes.FirstOrDefault(b => b.UserId == userId && b.CommentId == id);
            if (existLike == null)
            {
                _context.BookCommentLikes.Add(new BookCommentLike
                {
                    CommentId = id,
                    UserId = userId,
                    CreatedDate = DateTime.Now
                });
                Save();
                var bookComment = _context.BookComments.Find(id);
                bookComment.Like++;
                InsertOrUpdate(bookComment);
                Save();
                feedback.IsSuccess = true;
            }
            else
            {
                _context.BookCommentLikes.Remove(existLike);
                Save();
                var bookComment = _context.BookComments.Find(id);
                bookComment.Like--;
                InsertOrUpdate(bookComment);
                Save();
                feedback.IsSuccess = true;
                feedback.Message = Constant.ExisBookCommentLike;
            }
            return feedback;
        }

        public void DeleteAllCommentByBookId(int id)
        {
            var listLikeBookId = _context.BookComments.Where(bc => bc.BookId == id).Select(bc => bc.Id).ToList();

            foreach (var commentId in listLikeBookId)
            {
                var bookCommentLikes =
                    _context.BookCommentLikes.Where(cl => cl.CommentId == commentId).ToList();
                foreach (var bookCommentLike in bookCommentLikes)
                {
                    _context.BookCommentLikes.Remove(bookCommentLike);
                    Save();
                }
                //delete report comment
                List<ReportOnBookComment> listReportCommentId =
                    _context.ReportOnBookComments.Where(rc => rc.BookCommentId == commentId).ToList();
                foreach (ReportOnBookComment reportOnComment in listReportCommentId)
                {
                    _context.ReportOnBookComments.Remove(reportOnComment);
                    Save();
                }
                Delete(commentId);
                Save();
            }
        }

        public void Report(int id, int userId)
        {
            ReportOnBookComment found =
                _context.ReportOnBookComments.FirstOrDefault(c => c.BookCommentId == id && c.UserId == userId);
            if (found != null) return;
            var reportComment = new ReportOnBookComment
                                    {
                                        BookCommentId = id,
                                        UserId = userId,
                                        ReportedDate = DateTime.Now
                                    };
            _context.ReportOnBookComments.Add(reportComment);
            _context.SaveChanges();
        }


        public List<BookComment> FetchCommentsByPage(int bookId, int pageNumber,int userId)
        {
            List<BookComment> comments =
                _context.BookComments.Where(c => c.BookId == bookId&& c.IsBlocked==false)
                .OrderByDescending(c => c.CreatedDate)
                .Skip(Constant.MaximunCommentPerChapter * (pageNumber - 1))
                .Take(Constant.MaximunCommentPerChapter)
                .ToList();
            foreach (var bookComment in comments)
            {
                bookComment.User = _context.Users.FirstOrDefault(u => u.Id == bookComment.UserId);
                bookComment.IsLiked =
                    _context.BookCommentLikes.Any(bcl => bcl.CommentId == bookComment.Id && bcl.UserId == userId);
                bookComment.IsReported =
                       _context.ReportOnBookComments.Any(
                           rocc => rocc.BookCommentId == bookComment.Id && rocc.UserId == userId);
                bookComment.IsAuthorized = bookComment.UserId == userId;
            }
            return comments;
        }

        #endregion
    }

    #region Nested type: IBookCommentRepository

    public interface IBookCommentRepository
    {
        IQueryable<BookComment> All { get; }
        BookComment Find(int id);
        void InsertOrUpdate(BookComment author);
        void Delete(int id);
        void Save();

        List<BookComment> FetchCommentsByPage(int bookId, int pageNumber,int userId);
        DataFeedback Like(int id, int i);
        void DeleteAllCommentByBookId(int id);
        void Report(int id, int userId);
    }

    #endregion
}